package com.alcatel_lucent.osp.model;

import org.apache.struts2.json.annotations.JSON;
import org.hibernate.annotations.Fetch;

import javax.persistence.*;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Map;

@SuppressWarnings("serial")
@Entity
@Table(name = "REQUEST")
public class Request extends BaseEntity {

    private Category category;

    private Type type;
    private String description;

    private Timestamp reportTime;
    private Timestamp lastUpdateTime;
    private Date targetDate;

    private Timestamp remindDate;

    private RequestStatus status = RequestStatus.NEW;

    private User lastUpdateBy;
    private User reportBy;

    public Collection<User> copyList;

    private Collection<Comment> comments;
    private Collection<Attachment> attachments;

    private Map<String, String> attributes;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "IdRequestGenerator")
    @SequenceGenerator(name = "IdRequestGenerator", sequenceName = "ID_REQUEST", allocationSize = 20)
    @Override
    public Long getId() {
        return super.getId();
    }

    @Transient
    public String getReqNo() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
        DecimalFormat nf = new DecimalFormat("000000");
        return sdf.format(reportTime) + nf.format(getId());
    }

    @Column(name = "REMIND_DATE")
    public Timestamp getRemindDate() {
        return remindDate;
    }

    public void setRemindDate(Timestamp remindDate) {
        this.remindDate = remindDate;
    }

    @ManyToMany
    @JoinTable(name = "REQUEST_COPY_LIST_USER",
            joinColumns = @JoinColumn(name = "REQUEST_ID"),
            inverseJoinColumns = @JoinColumn(name = "USER_CSL")
    )
    public Collection<User> getCopyList() {
        return copyList;
    }

    public void setCopyList(Collection<User> copyList) {
        this.copyList = copyList;
    }

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "REQUEST_ATTRIBUTES", joinColumns = @JoinColumn(name = "REQUEST_ID"))
    @MapKeyColumn(name = "NAME")
    @Column(name = "VALUE")
    public Map<String, String> getAttributes() {
        return attributes;
    }

    public void setAttributes(Map<String, String> attributes) {
        this.attributes = attributes;
    }

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "REQUEST_ID")
    public Collection<Attachment> getAttachments() {
        return attachments;
    }

    public void setAttachments(Collection<Attachment> attachments) {
        this.attachments = attachments;
    }

    @OneToMany
    @JoinColumn(name = "REQUEST_ID")
    public Collection<Comment> getComments() {
        return comments;
    }

    public void setComments(Collection<Comment> comments) {
        this.comments = comments;
    }

    @ManyToOne
    @JoinColumn(name = "CATEGORY_ID")
    public Category getCategory() {
        return category;
    }

    public void setCategory(Category category) {
        this.category = category;
    }

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "TYPE_ID")
    public Type getType() {
        return type;
    }

    public void setType(Type type) {
        this.type = type;
    }

    @Column(name = "DESCRIPTION", length = 4096)
    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @JSON(format = "yyyy-MM-dd")
    @Column(name = "TARGET_DATE")
    public Date getTargetDate() {
        return targetDate;
    }

    public void setTargetDate(Date targetDate) {
        this.targetDate = targetDate;
    }

    @Column(name = "STATUS")
    @Enumerated(EnumType.ORDINAL) //enum persisted as ordinal in database
    public RequestStatus getStatus() {
        return status;
    }

    public void setStatus(RequestStatus status) {
        this.status = status;
    }


    @JSON(format = "yyyy-MM-dd HH:mm:ss")
    @Column(name = "REPORT_TIME")
    public Timestamp getReportTime() {
        return reportTime;
    }

    public void setReportTime(Timestamp reportTime) {
        this.reportTime = reportTime;
    }

    @ManyToOne
    @JoinColumn(name = "REPORT_BY")
    public User getReportBy() {
        return reportBy;
    }

    public void setReportBy(User reportBy) {
        this.reportBy = reportBy;
    }

    @ManyToOne
    @JoinColumn(name = "LAST_UPDATE_BY")
    public User getLastUpdateBy() {
        return lastUpdateBy;
    }

    public void setLastUpdateBy(User lastUpdateBy) {
        this.lastUpdateBy = lastUpdateBy;
    }

    @JSON(format = "yyyy-MM-dd HH:mm:ss")
    @Column(name = "LAST_UPDATE_TIME")
    public Timestamp getLastUpdateTime() {
        return lastUpdateTime;
    }

    public void setLastUpdateTime(Timestamp lastUpdateTime) {
        this.lastUpdateTime = lastUpdateTime;
    }

    @Transient
    public boolean isOwner(User user) {
        Collection<User> owners = category.getOwners();
        if (owners != null) {
            for (User owner : owners) {
                if (owner.getCsl().equals(user.getCsl())) return true;
            }
        }
        return false;
    }

    public String toJSONString() {
        return "{}";
    }

    @Transient
    public String get(String attrName){
        return this.attributes.get(attrName);
    }

}
